import tkinter as tk
from tkinter import ttk
from datetime import datetime
import random
from ATMsystem import BankSimulation
from bank01.BankDatabase import BankDatabase


class BankSimulator:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("银行模拟系统界面")

        # 创建滚动条
        scrollbar = tk.Scrollbar(self.root, orient=tk.VERTICAL)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        # 创建 Canvas 组件
        self.canvas = tk.Canvas(self.root, yscrollcommand=scrollbar.set)
        self.canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        # 创建数据框架
        self.data_frame = ttk.Frame(self.canvas)
        self.data_frame.pack(padx=10, pady=10)

        # 将数据框架放置在 Canvas 中
        self.canvas.create_window((0, 0), window=self.data_frame, anchor=tk.NW)

        # 绑定滚动条
        scrollbar.config(command=self.canvas.yview)

        # 确保 Canvas 可以正确滚动
        self.data_frame.bind("<Configure>", self.on_frame_configure)

        self.create_widgets()
        self.root.geometry("500x500")
        self.simulation = BankSimulation()

    def on_frame_configure(self, event):
        self.canvas.configure(scrollregion=self.canvas.bbox("all"))
    def create_widgets(self):
        # 设置标签信息
        label1 = tk.Label(self.data_frame, text='银行营业时间(h)：')
        label1.grid(row=0, column=0)
        label2 = tk.Label(self.data_frame, text='银行歇业时间(h)：')
        label2.grid(row=1, column=0)
        label3 = tk.Label(self.data_frame, text='模拟人数：')
        label3.grid(row=2, column=0)

        # 创建输入框
        self.entry1 = tk.Entry(self.data_frame, width=40)
        self.entry1.grid(row=0, column=1, padx=10, pady=5)
        self.entry2 = tk.Entry(self.data_frame, width=40)
        self.entry2.grid(row=1, column=1, padx=10, pady=5)
        self.entry3 = tk.Entry(self.data_frame, width=40)
        self.entry3.grid(row=2, column=1, padx=10, pady=5)

        # 创建按键
        tk.Button(self.data_frame, text='产生数据', command=self.start_simulation).grid(row=3, column=0, sticky=tk.W,
                                                                                        padx=30, pady=5)
        tk.Button(self.data_frame, text='结果展示', command=self.showRes).grid(row=3, column=1, sticky=tk.E, padx=30,
                                                                                 pady=5)
    # 结果展示
    def showRes(self):
        self.result_window = tk.Toplevel(self.root)
        tk.Label(self.result_window,
                 text=("平均每位客户逗留时间(m): {}".format(self.simulation.calculate_average_stay_time())), width=50, height=3).grid(row=0, column=0)

        tk.Label(self.result_window,
                 text=("每窗口服务客户数: {}".format(self.simulation.calculate_average_service_per_window())), width=50, height=3).grid(row=1, column=0)
        tk.Label(self.result_window,
                 text=("每窗口服务业务类型数: {}".format(self.simulation.service_type_per_window())), width=50, height=3).grid(row=2, column=0)
        # self.root.quit()

        # self.simulation


    def start_simulation(self):
        open_time = int(self.entry1.get())
        close_time = int(self.entry2.get())
        peo_num = int(self.entry3.get())
        # self.root.withdraw()  # 隐藏主界面
        self.simulation_window = tk.Toplevel(self.root)
        self.simulation_window.title("银行模拟系统")
        self.run_simulation(open_time, close_time, peo_num)
        self.simulation_window.mainloop()  # 等待窗口关闭后再进行后续操作
        self.simulation.print_result()


    def run_simulation(self, open_time, close_time, peo_num):
        menu = ['时间', '人物', '业务', '状态']
        datas = self.generate_data(open_time, close_time, peo_num)
        for data in datas:
            print(data)
        # 创建滚动条
        scrollbar = tk.Scrollbar(self.simulation_window, orient=tk.VERTICAL)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        # 创建 Canvas 组件
        canvas = tk.Canvas(self.simulation_window, yscrollcommand=scrollbar.set)
        canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        # 创建数据框架
        data_frame = ttk.Frame(canvas)
        data_frame.pack(padx=10, pady=10)
        # 将数据框架放置在 Canvas 中
        canvas.create_window((0, 0), window=data_frame, anchor=tk.NW)

        self.simulation_window.geometry("600x600")
        # 显示菜单
        for i, item in enumerate(menu):
            tk.Label(data_frame, text=item, width=20, height=2).grid(row=0, column=i)
        # 显示数据
        for i, item in enumerate(datas):
            formatted_time = item[2].strftime("%Y-%m-%d %H:%M:%S")
            tk.Label(data_frame, text=formatted_time, width=20, height=2).grid(row=i + 1, column=0)
            tk.Label(data_frame, text=item[0], width=15, height=2).grid(row=i + 1, column=1)
            tk.Label(data_frame, text=item[1], width=15, height=2).grid(row=i + 1, column=2)
            tk.Label(data_frame, text="排队", width=15, height=2).grid(row=i + 1, column=3)
        # 配置滚动条的命令为 Canvas 组件的 yview 属性
        scrollbar.config(command=canvas.yview)
        def on_mousewheel(event):
            if event.delta < 0:
                canvas.yview_scroll(1, "units")
            elif canvas.canvasy(0) > 0:
                canvas.yview_scroll(-1, "units")
        # 绑定鼠标滚轮事件到 Canvas 组件上
        canvas.bind_all("<MouseWheel>", on_mousewheel)
        tk.Button(self.data_frame, text='开始模拟', command=lambda: self.run_start_algorithm(data_frame, peo_num, datas)).grid(row=4, column=1, sticky=tk.W, padx=30, pady=5)

    def run_start_algorithm(self, data_frame, peo_num, datas):
        row = 1
        queue = [0, 0, 0, 0]
        def remove_customer_info(data_frame, row, i):
            for label in data_frame.grid_slaves():
                if int(label.grid_info()["row"]) == row:
                    label.destroy()
            queue[i] = 0

        def update_state(data_frame, row, num):
            for label in data_frame.grid_slaves():
                if int(label.grid_info()["row"]) == row and int(label.grid_info()["column"]) == 3:
                    label.config(text=num)

        remove_customer_info(self.data_frame, 4, 1)

        def serve_next_customer():
            nonlocal row, queue
            for i in range(len(queue)):
                if queue[i] == 0:
                    update_state(data_frame, row, i + 1)
                    time = random.randint(100, 1000)
                    self.simulation.simulate(datas[row-1][0], i, datas[row-1][1], int(time/10))
                    tk.Label(self.data_frame, text="{}号顾客在{}号窗口办理{}业务,花费{}分钟".format(datas[row-1][0], i, datas[row-1][1], int(time/10)), width=40).grid(row=row+4, column=1)

                    self.simulation_window.after(time, remove_customer_info, data_frame, row, i)
                    queue[i] = row
                    row += 1
                    break  # 为了确保只为一个窗口安排下一个顾客的到达和服务
            if row <= peo_num:
                self.simulation_window.after(100, serve_next_customer)  # 继续服务下一个顾客
            else:
                self.simulation_window.after(200, self.simulation_window.destroy())

        # 开始服务第一个顾客
        serve_next_customer()


    def generate_data(self, start_hour, end_hour, num_entries):
        operations = ['存款', '挂失', '取款', '还贷']
        data = []
        for i in range(1, num_entries + 1):
            operation = random.choice(operations)
            amount = round(random.uniform(1000, 10000), 2)
            # 生成随机小时、分钟和秒
            random_hour = random.randint(start_hour, end_hour - 1)
            random_minute = random.randint(0, 59)
            random_second = random.randint(0, 59)
            # 获取当前日期
            current_date = datetime.now().date()

            # 创建随机时间的datetime对象
            random_time = datetime(current_date.year, current_date.month, current_date.day, random_hour, random_minute,
                                   random_second)
            data.append((i, operation, random_time, amount))
            data = sorted(data, key=lambda x: x[2])
        return data

if __name__ == '__main__':
    # bank = BankDatabase(host='182.92.6.98', port=8089, user='root', password='12345678', database='bank')
    bank_simulator = BankSimulator()
    bank_simulator.root.mainloop()